## pycontact.py is a library for talking to the iContact (http://www.icontact.com) API 2.0

import pycurl
import json
from StringIO import StringIO

class Config:
	def __init__(self, user, password, appid):
		"""Set up user- and application-specifc configuration
		
		user        iContact username
		password    API password for username
		appid       API application id
		"""
		self.username   = user
		self.password   = password
		self.appid      = appid
		
		# Defaults
#		self.base_url    = 'https://app.beta.icontact.com/icp'
		self.base_url    = 'https://app.icontact.com'
		self.accept      = 'application/json'

class Api:
	"""Class for requesting and sending data to the iContact Api"""
	
	def __init__(self, config, verbose=False):
		"""Initialize an API handle
		
		config     Config object
		verbose    Display verbose libcurl output
		"""
		self.config  = config
		self.verbose = verbose

	def call(self, resource, method, data=None):
		"""Call the iContact API

		resource  resource to call, i. e. /a or /a/123/c
		method    one of: get, post, put, delete
		data      data to encode and send on post and put requests
		
		Returns (code, response)
		"""
		resource = self.config.base_url + resource
		method = method.upper()
		response = StringIO()

		headers = [
			'Accept: ' + self.config.accept,
			'Content-Type: application/json',
			'Api-Version: 2.0',
			'Api-AppId: ' + self.config.appid,
			'Api-Username: ' + self.config.username,
			'Api-Password: ' + self.config.password,
		]

		handle = pycurl.Curl()

		handle.setopt(pycurl.URL, resource)
		handle.setopt(pycurl.HTTPHEADER, headers)
		handle.setopt(pycurl.VERBOSE, self.verbose)
		# Uncomment these lines if working in the beta environment
#		handle.setopt(pycurl.SSL_VERIFYPEER, False)
#		handle.setopt(pycurl.SSL_VERIFYHOST, False)

		if (data is not None):
			data = json.write(data)

		if (method == 'POST'):
			handle.setopt(pycurl.POST, True)
			handle.setopt(pycurl.POSTFIELDS, data)
		elif (method == 'DELETE'):
			handle.setopt(pycurl.CUSTOMREQUEST, 'DELETE')
		elif (method == 'PUT'):
			indata = StringIO(data)
			handle.setopt(pycurl.PUT, True)
			handle.setopt(pycurl.READFUNCTION, indata.read)

		handle.setopt(pycurl.WRITEFUNCTION, response.write)
		handle.perform()

		code = handle.getinfo(pycurl.RESPONSE_CODE)
		response = json.read(response.getvalue())
		
		handle.close()
		
		return (code, response)

	def delete(self, resource):
		"""Call the iContact API with a delete request

		resource  resource to call, i. e. /a or /a/123/c
		
		Returns (code, response)
		"""
		return self.call(resource, 'DELETE')

	def get(self, resource):
		"""Call the iContact API with a get request

		resource  resource to call, i. e. /a or /a/123/c
		
		Returns (code, response)
		"""
		return self.call(resource, 'GET')

	def post(self, resource, data):
		"""Call the iContact API with a post request
		
		POSTSs to the API update only the fields given
		in the data

		resource  resource to call, i. e. /a or /a/123/c
		data      data to post
		
		Returns (code, response)
		"""
		return self.call(resource, 'POST', data)

	def put(self, resource, data):
		"""Call the iContact API with a put request
		
		PUTs to the API will blank out any fields not given
		and update with the fields given

		resource  resource to call, i. e. /a or /a/123/c
		data      data to put
		
		Returns (code, response)
		"""
		return self.call(resource, 'PUT', data)

